home *** CD-ROM | disk | FTP | other *** search
- #include <Events.h>
- #include <Resources.h>
- #include <Memory.h>
- #include <ToolUtils.h>
- #include <Menus.h>
-
- #define CurMenuID (*(short *)0xB54)
- #define CurMenuItem (*(short *)0xB56)
-
- #include "Appearance.h"
-
- /* Character Codes */
- enum
- {
- kEnterKey = 0x03,
- kReturnKey = 0x0D,
- kEscapeKey = 0x1B,
- kLeftArrowKey = 0x1C,
- kRightArrowKey = 0x1D,
- kUpArrowKey = 0x1E,
- kDownArrowKey = 0x1F,
- kSpaceKey = 0x20,
- kDeleteKey = 0x08,
- kTabKey = 0x09,
- kPeriodKey = '.'
- };
-
- // Need to patch: MenuSelect, WaitMouseUp, GetMouse, SystemEvent
-
- #ifndef powerc
- #ifdef THINK_C
- #pragma parameter __D0 SetA4(__D0)
- pascal long SetA4(long newA4) = 0xC18C;
-
- #define SetCurrentA4() SetA4((long)&main)
- #else
- #include <A4Stuff.h>
- // #include <SetUpA4.h>
- #endif
- #else
- #define SetCurrentA4() 0
- #define SetA4(x) 0
-
- ProcInfoType __procinfo = kCStackBased
- | RESULT_SIZE(kFourByteCode)
- | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(void *)));
- #endif
-
- pascal long (*gOldMenuSelect)(Point pt);
- pascal long myMenuSelect(Point pt);
- enum {
- uppMenuSelectProcInfo = kPascalStackBased | RESULT_SIZE(kFourByteCode) | STACK_ROUTINE_PARAMETER(1, kFourByteCode)
- };
-
-
- pascal short (*gOldWaitMouseUp)(void);
- pascal short myWaitMouseUp(void);
- enum {
- uppWaitMouseUpProcInfo = kPascalStackBased | RESULT_SIZE(kTwoByteCode)
- };
-
- pascal void (*gOldGetMouse)(Point *ptp);
- pascal void myGetMouse(Point *ptp);
- enum {
- uppGetMouseProcInfo = kPascalStackBased | STACK_ROUTINE_PARAMETER(1, kFourByteCode)
- };
-
- pascal short (*gOldSystemEvent)(EventRecord *theEvent);
- pascal short mySystemEvent(EventRecord *theEvent);
- enum {
- uppSystemEventProcInfo = kPascalStackBased | RESULT_SIZE(kTwoByteCode) | STACK_ROUTINE_PARAMETER(1, kFourByteCode)
- };
-
- enum {
- kIdle = 0,
- kInMenuSelect = 1
- } gMenuKeyState = kIdle;
-
- int gNeedItemRedraw;
- static short gHaveFakeMSResult = false;
- static long gFakeMSResult;
-
- void main(void)
- {
- long oldA4;
- THz oldZone;
-
- // Set up A4, so we can access our globals.
- oldA4 = SetCurrentA4();
-
- // Set the current zone to the system zone. In the 680x0 case, this
- // is not necessary, but it's not a bad idea and it keeps us out of
- // trouble when traps that we don't expect to have side effects
- // unexpectedlty allocate memory from the current zone. One example
- // of this is the NewRoutineDescriptor routine.
- oldZone = GetZone();
- SetZone(SystemZone());
-
- // We need to detach our code, so that we stay around.
- DetachResource(GetResource('INIT', 237));
-
- // Remember the old implementation of WaitMouseUp and MenuSelect and GetMouse and SystemEvent.
- gOldWaitMouseUp = (void *) GetToolTrapAddress(0xA977);
- gOldGetMouse = (void *) GetToolTrapAddress(0xA972);
- gOldSystemEvent = (void *) GetToolTrapAddress(0xA9B2);
- gOldMenuSelect = (void *) GetToolTrapAddress(0xA93D);
-
- // Patch ourselves in.
- SetToolTrapAddress(NewRoutineDescriptor((ProcPtr) &myWaitMouseUp,uppWaitMouseUpProcInfo,kPowerPCISA), 0xA977);
- SetToolTrapAddress(NewRoutineDescriptor((ProcPtr) &myGetMouse,uppGetMouseProcInfo,kPowerPCISA), 0xA972);
- SetToolTrapAddress(NewRoutineDescriptor((ProcPtr) &mySystemEvent,uppSystemEventProcInfo,kPowerPCISA), 0xA9B2);
- SetToolTrapAddress(NewRoutineDescriptor((ProcPtr) &myMenuSelect,uppMenuSelectProcInfo,kPowerPCISA), 0xA93D);
-
- // Restore the old zone again
- SetZone(oldZone);
-
- // And restore the value of A4 on the way out.
- SetA4(oldA4);
- }
-
- /*------------------------------------------------------------------
- ConvertKeyToChar [internal]
-
- This function uses international utilities to convert a specific
- key code from the keyboard to a character given the current script.
-
- Parameters:
- In: inKeyCode - key code for current keyboard
- Out: (return) - associated char code
- ------------------------------------------------------------------*/
-
- static UInt8
- ConvertKeyToChar(UInt8 inKeyCode)
- {
- static SInt16 sPrevKchrID = 237;
- static UInt8 sCharsOfKeys[256];
- SInt16 curKchrID;
- UInt8 charCode;
- UInt32 zero = 0;
-
- curKchrID = GetScriptVariable(smCurrentScript, smScriptKeys);
-
- // If this is the first time through here or if the
- // script has changed since we last executed this, we
- // need to update our key-to-char code mapping.
- if (curKchrID != sPrevKchrID)
- {
- Handle kchrRsrc;
- UInt16 keyCode;
-
- kchrRsrc = GetResource('KCHR', curKchrID);
- if (kchrRsrc == NULL)
- kchrRsrc = GetIndResource('KCHR', 1);
-
- if (kchrRsrc == NULL) DebugStr("\pkchrRsrc == NULL");
-
- for (keyCode = 0; keyCode <= 255; keyCode++)
- {
- sCharsOfKeys[keyCode] = (keyCode <= 127 ?
- KeyTranslate(*kchrRsrc, keyCode, &zero) : -1);
- }
-
- sPrevKchrID = curKchrID;
- }
-
- // Now that we have a valid mapping array, the translation
- // is as simple as an array lookup.
- charCode = sCharsOfKeys[(UInt8)inKeyCode];
-
- // Convert from lower-case to upper-case if alpha character
- if (charCode >= 'a' && charCode <= 'z')
- charCode += 'A' - 'a';
-
- return charCode;
- }
-
- static void
- GetKeyASCII( UInt8 charCode,
- UInt8 keyCode,
- UInt8* outText)
- {
- const static UInt8 sStringLookupArray[] = {
- 0x01, 0x03, 0x04, 0x05, 0x08, 0x09, 0x0B, 0x0C, 0x0D, 0x1B, 0x1B,
- 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x7F,
- 0x7A, 0x78, 0x63, 0x76, 0x60, 0x61, 0x62, 0x64, 0x65, 0x6D, 0x67,
- 0x6F, 0x69, 0x6B, 0x71
- };
-
- // Convert the key code to a character using the current script
- charCode = ConvertKeyToChar(keyCode);
-
- // If we are in the range of standard characters, just use the character
- if (1) // if (charCode > kSpaceKey && charCode <= 0x7E)
- {
- if (1) // if (keyCode < 0x40)
- {
- // Standard keys
- outText[0] = 1;
- outText[1] = charCode;
- }
- else
- {
- // Keypad keys
- outText[0] = 3;
- outText[1] = '[';
- outText[2] = charCode;
- outText[3] = ']';
- }
- }
- else
- {
- UInt16 itemIndex;
- const UInt8* lookup;
-
- // Special keys which are represented by strings in a resource
- lookup = sStringLookupArray;
-
- if (charCode == kEscapeKey)
- {
- // Multiple keys map to the escape char code
- itemIndex = (keyCode <= 0x40) ? 11 : 12;
- }
- else
- {
- // Scan the array for a match with the char code or key code
- for (itemIndex = 2; itemIndex <= 33; itemIndex++, lookup++)
- {
- if (itemIndex <= 18)
- {
- if (charCode == *lookup)
- break;
- }
- else
- {
- if (keyCode == *lookup)
- break;
- }
- }
-
- if (itemIndex > 33)
- itemIndex = 1;
- }
-
- // GetIndString(outText, kKeyStrId, itemIndex);
- }
- }
-
- static void TranslateEvent(short emodifiers, long emessage, short *modifiersp, short *ASCII)
- {
- short modifiers = 0;
- if (!(emodifiers & cmdKey)) modifiers |= kMenuNoCommandModifier;
- if (emodifiers & shiftKey) modifiers |= kMenuShiftModifier;
- if (emodifiers & optionKey) modifiers |= kMenuOptionModifier;
- if (emodifiers & controlKey) modifiers |= kMenuControlModifier;
- *modifiersp = modifiers;
- *ASCII = ConvertKeyToChar((char) (emessage >> 8));
- }
-
- static int IsValidKeyEvent(EventRecord *erp) {
- char ASCIIval = erp->message;
-
- if (erp->modifiers & (cmdKey || optionKey || controlKey)) return true;
- if (ASCIIval < ' ' || ASCIIval > 0x7F) return true;
- return false;
- }
-
-
- pascal short myWaitMouseUp(void)
- {
- long oldA4;
- short result;
- long temp;
- short menuID, menuItem;
- short menuModifiers, menuASCII;
- MenuHandle mh;
- EventRecord keyEvent;
-
- // Set up A4, so we can access our globals.
- oldA4 = SetCurrentA4();
-
- if (gMenuKeyState == kInMenuSelect) {
- menuID = CurMenuID;
- menuItem = CurMenuItem;
-
- if (menuID && menuItem) {
- mh = GetMHandle(menuID);
- if (mh && ((**mh).enableFlags >> menuItem) & 1) {
- if (GetOSEvent(keyDownMask, &keyEvent) && IsValidKeyEvent(&keyEvent)) {
- if (kDeleteKey == (char)keyEvent.message) {
- SetItemCmd(mh, menuItem, 0);
- SetMenuItemModifiers(mh, menuItem, 0);
- gNeedItemRedraw = 5;
- } else {
- TranslateEvent(keyEvent.modifiers, keyEvent.message, &menuModifiers, &menuASCII);
- SetItemCmd(mh, menuItem, menuASCII);
- SetMenuItemModifiers(mh, menuItem, menuModifiers);
- gNeedItemRedraw = 5;
- }
- }
- }
- }
- }
-
- // Call the old WaitMouseUp:
- #ifndef powerc
- result = gOldWaitMouseUp();
- #else
- result = CallUniversalProc((UniversalProcPtr)gOldWaitMouseUp, uppWaitMouseUpProcInfo);
- #endif
-
- // And restore the value of A4 on the way out.
- SetA4(oldA4);
-
- return result;
- }
-
- pascal void myGetMouse(Point *ptp)
- {
- long oldA4;
-
- // Set up A4, so we can access our globals.
- oldA4 = SetCurrentA4();
-
- if (gNeedItemRedraw) {
- gNeedItemRedraw --;
- ptp->h = 0x0237;
- ptp->v = 0x0237;
- } else {
- // Call the old GetMouse:
- #ifndef powerc
- gOldGetMouse(ptp);
- #else
- CallUniversalProc((UniversalProcPtr)gOldGetMouse, uppGetMouseProcInfo, ptp);
- #endif
- }
-
- // And restore the value of A4 on the way out.
- SetA4(oldA4);
- }
-
- pascal short mySystemEvent(EventRecord *erp)
- {
- long oldA4;
- short result;
- long fakeMS;
- char ASCIIval;
-
- // Set up A4, so we can access our globals.
- oldA4 = SetCurrentA4();
-
- if (erp->what == keyDown || erp->what == autoKey)
- {
- ASCIIval = erp->message;
- if (IsValidKeyEvent(erp))
- {
- gFakeMSResult = MenuEvent(erp);
- if ((gFakeMSResult & 0xFFFF0000) && (gFakeMSResult & 0xFFFF)) {
- gHaveFakeMSResult = true;
- erp->what = mouseDown;
- erp->where.h = 37;
- erp->where.v = 2;
- } else
- gHaveFakeMSResult = false;
- }
- }
-
- // Call the old SystemEvent:
- #ifndef powerc
- result = gOldSystemEvent(erp);
- #else
- result = CallUniversalProc((UniversalProcPtr)gOldSystemEvent, uppSystemEventProcInfo, erp);
- #endif
-
- // And restore the value of A4 on the way out.
- SetA4(oldA4);
-
- return result;
- }
-
- pascal long myMenuSelect(Point pt)
- {
- // Set up A4, so we can access our globals.
- long oldA4;
- long result;
- int oldState;
-
- oldA4 = SetCurrentA4();
-
- oldState = gMenuKeyState;
- gMenuKeyState = kInMenuSelect;
-
- if (gHaveFakeMSResult) {
- gHaveFakeMSResult = false;
- result = gFakeMSResult;
- } else {
- // Call the old MenuSelect:
- #ifndef powerc
- result = gOldMenuSelect(theEvent);
- #else
- result = CallUniversalProc((UniversalProcPtr)gOldMenuSelect, uppMenuSelectProcInfo, pt);
- #endif
- }
-
- gMenuKeyState = kIdle;
-
- // And restore the value of A4 on the way out.
- SetA4(oldA4);
-
- return result;
- }
-